/**
 * This class holds all of the GUI objects and is responsible for how the simulator looks.
 * It also interacts with memory manager to keep everything up to date. This class
 * also keeps track of how many cycles have passed.
 * MemSimView.java
 */

package memsim;
import memsim.instructions.*;

import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.*;
import java.awt.*;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.event.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JFileChooser;
import java.io.File;

/**
 * The application's main frame.
 */
public class MemSimView extends FrameView {


    public MemSimView(SingleFrameApplication app) {
        super(app);

        
        //regHandler = registers
        //memView = ram
        //alu


        initComponents();
        columnNamesV.add("Address");
        columnNamesV.add("Value");
        regColNamesV.add("Register:");
        regColNamesV.add("value:");

        alu = new Alu();
        
        //i want to construct a 128 x 2 matrix, with the first being address and second being value
        memView = new MemoryManager();
        Object[][] curView = memView.getPage(0);
        memTableModel = new MemoryTableModel(curView,columnNames);
        memViewer.setModel(memTableModel);

        String[] addressList = memView.getAddresses();
        for(int i = 0; i < addressList.length; i++)
            choicePage.add(addressList[i]);

        memViewer.getModel().addTableModelListener(new TableModelListener()
        {
               public void tableChanged(TableModelEvent e) {

                   if(manualUpdate)
                   {
                        memView.setValue(memViewer.getValueAt(memViewer.getSelectedRow(), 0).toString(), memViewer.getValueAt(memViewer.getSelectedRow(), 1));
                   }
                   
                   manualUpdate = true;

               }

        });

        int[] tempRegData = regHandler.getGenRegs();
        regData = new Object[tempRegData.length][2];
        for(int i = 0; i < tempRegData.length; i++)
        {
            regData[i][1] = tempRegData[i];
            regData[i][0] = regNames[i];
        }

        regModel = new MemoryTableModel(regData, regColNames);
        regViewer.setModel(regModel);

        regViewer.getModel().addTableModelListener(new TableModelListener()
        {
               public void tableChanged(TableModelEvent e) {

                   if(manualUpdate)
                   {
                       if(currentRep == 0)
                       {
                           regHandler.setValue(regViewer.getSelectedRow(), Integer.parseInt(regViewer.getValueAt(regViewer.getSelectedRow(), 1).toString()));
                       }
                       else
                       {
                           regHandler.setValue(regViewer.getSelectedRow(), regViewer.getValueAt(regViewer.getSelectedRow(), 1).toString());
                       }

                       
                       //update the register data with the new value
                       int[] tempRegData = regHandler.getGenRegs();
                       for(int i = 0; i < tempRegData.length; i++)
                       {
                            regData[i][1] = tempRegData[i];
                       }
                   }

                   manualUpdate = true;

               }

        });



        choicePage.addItemListener(new ItemListener()
        {
            
            public void itemStateChanged(ItemEvent IE)
            {

                //if the current representation is Hex, update the table by switching pages first, then convert evreything on that page to hex
                //can be made cleaner by doing a straight conversion, but that requires array manipulation as opposed to vector
                if(currentRep == 1)
                {

                    int temp = choicePage.getSelectedIndex();
                    refreshTableArray(memView.getPage(temp), columnNames,memViewer);

                    DefaultTableModel tempModel = (DefaultTableModel)memViewer.getModel();
                    Vector tempVector = tempModel.getDataVector();
                    tempVector = dec2Hex(tempVector);

                    refreshTableVector(tempVector, columnNamesV, memViewer);



                }
                else
                {
                    int temp = choicePage.getSelectedIndex();
                    refreshTableArray(memView.getPage(temp), columnNames,memViewer);
                    

                }
            }
        });
        System.out.println(memViewer.getSelectionModel().getAnchorSelectionIndex());
        

        gotoBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                String[] str = addrFld.getText().split("0x");
                int location = 0;
                if(str.length == 1)
                {
                    location = Integer.parseInt(str[0], 16);
                }
                else
                {
                    location = Integer.parseInt(str[1], 16);
                }

                int pageNum = 0;
                int index = 0;
                if(location % 4 == 0)
                {
                    index = location / 4;
                    while((location - 508) > 0)
                    {
                        pageNum++;
                        location -= 508;
                    }

                    refreshTableArray(memView.getPage(pageNum), columnNames, memViewer);


                }
                else
                {
                    JOptionPane.showMessageDialog(new JFrame(), "You have entered an invalid address", "Invalid Address", JOptionPane.ERROR_MESSAGE);
                }

            }

        });

        /**
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         */
        loadBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e){
                String[] str = addrFld.getText().split("0x");
                int location = 0;
                if(str.length == 1)
                {
                    location = Integer.parseInt(str[0], 16);
                }
                else
                {
                    location = Integer.parseInt(str[1], 16);
                }

                int pageNum = 0;
                int index = 0;
                if(location % 4 == 0)
                {
                    index = location / 4;
                    while((location - 508) > 0)
                    {
                        pageNum++;
                        location -= 508;
                    }
                    System.out.println("ping4");
                    //Object temp = memView.getValue(pageNum, index);
                    //regZero.setText("R0: 0x"+temp.toString());
//                    updateCycle(memView.getLatency(pageNum));

                }
                else
                {
                    JOptionPane.showMessageDialog(new JFrame(), "You have entered an invalid address", "Invalid Address", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        /**
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         * DO NOT USE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
         */
        storeBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e){
                String[] str = addrFld.getText().split("0x");
                int location = 0;
                if(str.length == 1)
                {
                    location = Integer.parseInt(str[0], 16);
                }
                else
                {
                    location = Integer.parseInt(str[1], 16);
                }

                int pageNum = 0;
                int index = 0;
                if(location % 4 == 0)
                {
                    index = location / 4;
                    while((location - 508) > 0)
                    {
                        pageNum++;
                        location -= 508;
                    }
                    //we gotta fix magic numbers
             //       Object temp = regZero.getText().substring(4);
                   // memView.setValue(pageNum, index, temp);
//                    updateCycle(memView.getLatency(pageNum));
                }
                else
                {
                    JOptionPane.showMessageDialog(new JFrame(), "You have entered an invalid address", "Invalid Address", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

/*       regZero.addActionListener(new ActionListener()
       {
           public void actionPerformed(ActionEvent e){
               String str = (String)JOptionPane.showInputDialog("Please enter desired value:");
               if(currentRep == 0)
               {
                   regZero.setText("R0: " + str);
               }
               else if(currentRep == 1)
               {
                   int hex = Integer.valueOf(str);
                   str = Integer.toHexString(hex);
                   regZero.setText("R0: 0x" + str);
               }
           }
       });

 *
 */
        exportBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e){
                final JFileChooser fc = new JFileChooser();
                String filename = "";
                int returnVal = fc.showSaveDialog(new JFrame());

                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = fc.getSelectedFile();
                    filename = file.getPath();
                }
                memView.writeToDisk(filename);
            }
        });

        importBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e){
                final JFileChooser fc = new JFileChooser();
                String filename = "";
                int returnVal = fc.showOpenDialog(new JFrame());

                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File file = fc.getSelectedFile();
                    filename = file.getName();
                    memView.loadFromDisk(file);
                }

                
                int temp = choicePage.getSelectedIndex();
                refreshTableArray(memView.getPage(temp), new String[]{"Address", "Value"}, memViewer);
            }
        });



        stepBtn.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                //regHandler = registers
                //memView = ram
                int content = Fetch.getFetch(memView, regHandler);
                DecodedObject dObj = Decode.decoded(content);
                Execute.getDecodeToExecute(dObj, alu,memView, regHandler);
                setSelection();
                updateCycle();

                Object[][] temp = regHandler.getTableArray();
                refreshTableArray(temp,regColNames,regViewer);
                int curPage = choicePage.getSelectedIndex();
                refreshTableArray(memView.getPage(curPage), columnNames, memViewer);
                
                System.out.println(dObj.getOpCode());
                System.out.println(dObj.getDstReg());
                System.out.println(dObj.getSrcReg1());
                System.out.println(dObj.getSrcReg2());


            }
        });

        //*****************************************************
        //add choices for switching to binary, hex, and dec
        choice1.add("Decimal");
        choice1.add("Hex");
        choice1.add("Float");
        choice1.addItemListener(new ItemListener()
        {

            public void itemStateChanged(ItemEvent IE) 
            {

                int newRep = choice1.getSelectedIndex();

                //if temp rep is a decimial, do a straight convert
                //else, convert to decimial, then do straight convert

                    //convert hex to decimal
                    if((newRep == 0))
                    {
                        /*update register too
                        String tempReg = regZero.getText();
                        tempReg = tempReg.substring(6);
                        int intReg = Integer.parseInt(tempReg, 16);
                        tempReg = intReg + "";
                        regZero.setText("R0: " + tempReg);
                        *done update*/

                         //get current page and just load current page instead - no conversion needed lulz
                        int curPage = choicePage.getSelectedIndex();

                        /*
                        DefaultTableModel tempModel = (DefaultTableModel)memViewer.getModel();
                        Vector tempVector = tempModel.getDataVector();
                        tempVector = hex2Dec(tempVector);
                         */

                        refreshTableArray(memView.getPage(curPage), columnNames, memViewer);
                        refreshTableArray(regData, regColNames,regViewer);

                    }
                
              
                    //convert from from decimal to hex
                    if(newRep == 1)
                    {
                        /*
                        //update reg to hex
                        String tempReg = regZero.getText();
                        tempReg = tempReg.substring(4);
                        int intReg = Integer.parseInt(tempReg);
                        tempReg = Integer.toHexString(intReg);
                        regZero.setText("R0: 0x" + tempReg);
                        //updated
                         */

                        /*
                        DefaultTableModel tempModel = (DefaultTableModel)memViewer.getModel();
                        Vector tempVector = tempModel.getDataVector();

                        tempVector = dec2Hex(tempVector);


                        refreshTableVector(tempVector, columnNamesV, memViewer);
                         */

                        int curPage = choicePage.getSelectedIndex();
                        Object[][] page = memView.getPage(curPage);
                        Object[][] pageTemp = new Object[memView.height()][memView.width()];
                        for(int i = 0; i < memView.height(); i++)
                        {
                            String temp = page[i][1].toString();

                            pageTemp[i][0] = page[i][0];
                            pageTemp[i][1] = toHex(Long.parseLong(temp));
                        }
                        refreshTableArray(pageTemp, columnNames, memViewer);


                        Vector tempVector;
                        DefaultTableModel tempModel2 = (DefaultTableModel)regViewer.getModel();
                        Vector tempVector2 = tempModel2.getDataVector();
                        tempVector = dec2Hex(tempVector2);

                        refreshTableVector(tempVector2, regColNamesV ,regViewer);


                        /////

                    }
                    if(newRep == 2)
                    {
                        int curPage = choicePage.getSelectedIndex();
                        Object[][] page = memView.getPage(curPage);
                        Object[][] pageTemp = new Object[memView.height()][memView.width()];
                        for(int i = 0; i < memView.height(); i++)
                        {
                            String temp = page[i][1].toString();

                            pageTemp[i][0] = page[i][0];
                            pageTemp[i][1] = Floats.toFloat(Long.parseLong(temp));
                        }
                        refreshTableArray(pageTemp, columnNames, memViewer);
                        
                    }

                
                currentRep = newRep;
                
             
            }
        });



        // status bar initialization - message timeout, idle icon and busy animation, etc



        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                statusMessageLabel.setText("");
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
                statusAnimationLabel.setIcon(busyIcons[busyIconIndex]);
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");
        statusAnimationLabel.setIcon(idleIcon);
        progressBar.setVisible(false);

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        statusAnimationLabel.setIcon(busyIcons[0]);
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(true);
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                    statusAnimationLabel.setIcon(idleIcon);
                    progressBar.setVisible(false);
                    progressBar.setValue(0);
                } else if ("message".equals(propertyName)) {
                    String text = (String)(evt.getNewValue());
                    statusMessageLabel.setText((text == null) ? "" : text);
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer)(evt.getNewValue());
                    progressBar.setVisible(true);
                    progressBar.setIndeterminate(false);
                    progressBar.setValue(value);
                }
            }
        });
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = MemSimApp.getApplication().getMainFrame();
            aboutBox = new MemSimAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        MemSimApp.getApplication().show(aboutBox);
    }

    private Vector hex2Dec(Vector input)
    {
        Vector output = input;
        Vector inputSeg;

        for(int i = 0; i < input.size(); i++)
        {
            String tempString;
            inputSeg = (Vector) input.get(i);
            try
            {
                tempString = (String) inputSeg.get(1);
            }
            catch (Exception E)
            {
                tempString = inputSeg.get(1).toString();
            }
            tempString = tempString.substring(2);

            int tempInt = Integer.parseInt(tempString, 16);

            inputSeg.set(1, tempInt);
            output.set(i, inputSeg);
        }


        return output;
    }

    //takes in a Vector of Vectors (in our case, Address, Value)
    private Vector dec2Hex(Vector input)
    {
        Vector output = input;
        Vector inputSeg; //holds the inner vectors
        //loops through all the vectors inside the vectors
        for(int i = 0; i < input.size(); i++)
        {
            inputSeg = (Vector) input.get(i);
            String tempString; //holds the converted hex string
            //assuming that second element of each vector contains a value
            //convert that value to a hex
            try
            {
                tempString = Long.toHexString((Long) inputSeg.get(1));
            } 
            catch (Exception E)
            {
                tempString = Long.toHexString(Long.parseLong(inputSeg.get(1).toString()));
            }
            tempString.toUpperCase(); //caps for convention
            tempString = "0x" + tempString;
            inputSeg.set(1, tempString);
            output.set(i, inputSeg); //updates value
        }
        return output;
    }
    private String toHex(long l)
    {
     String tempString; //holds the converted hex string
            //assuming that second element of each vector contains a value
            //convert that value to a hex
             tempString = Long.toHexString(l);
           
            tempString.toUpperCase(); //caps for convention
            tempString = "0x" + tempString;
            return tempString;
    }
    private boolean refreshTableArray(Object[][] curView, String[] names, JTable memViewer)
    {
        manualUpdate = false;
        MemoryTableModel temp =  (MemoryTableModel) memViewer.getModel();
        temp.setDataVector(curView, names);
        return true;
    }
    private boolean refreshTableVector(Vector data, Vector columnNames, JTable memViewer)
    {
        manualUpdate = false;
        MemoryTableModel temp =  (MemoryTableModel) memViewer.getModel();
        temp.setDataVector(data, columnNames);
        return true;
    }
    public void updateCycle()
    {
        cycleLbl.setText("Cycles Elapsed: " + alu.getCycleCount());
    }
    public float floatCalc(long value)
    {
        String binaryString = Long.toBinaryString(value);

        //leading zeros, make sure they're there
        while(binaryString.length() < 32)
        {
            binaryString = "0" + binaryString;
        }

        char signedBit = binaryString.charAt(0);
        String exponent = binaryString.substring(1, 9);
        String significand = "1" + binaryString.substring(9);

        //decode
        int exp = Integer.parseInt(exponent, 2);
        exp -= 127;

        float curFrac = 1;
        float sumFrac = 0;
        for(int i = 0; i < significand.length(); i++)
        {
            if(significand.charAt(i) == '1')
            {
                sumFrac += curFrac;
            }
            curFrac = curFrac / 2;
        }
        float tempFloat = (float)Math.pow(2, exp);
        float finalFloat = sumFrac * tempFloat;

        if(signedBit == 1)
            finalFloat = finalFloat * -1.0f;

        System.out.println(finalFloat);
        
       
        return 0.0f;
    }

    public void setSelection()
    {
        int pc = regHandler.getPC();
        int pageCounter = 0;
        while((pc -= 512) >= 0)
        {
            pageCounter++;
        }

        int selection = (regHandler.getPC() - (512 * pageCounter)) / 4;

        memViewer.setRowSelectionInterval(selection, selection);
        memViewer.changeSelection(selection, 0, false, false);
        memViewer.requestFocus();
    }


    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        exportBtn = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        memViewer = new javax.swing.JTable();
        choicePage = new java.awt.Choice();
        importBtn = new javax.swing.JButton();
        choice1 = new java.awt.Choice();
        storeBtn = new javax.swing.JButton();
        loadBtn = new javax.swing.JButton();
        addrLbl = new javax.swing.JLabel();
        addrFld = new javax.swing.JTextField();
        cycleLbl = new javax.swing.JLabel();
        gotoBtn = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        regViewer = new javax.swing.JTable();
        stepBtn = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        statusMessageLabel = new javax.swing.JLabel();
        statusAnimationLabel = new javax.swing.JLabel();
        progressBar = new javax.swing.JProgressBar();

        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setPreferredSize(new java.awt.Dimension(500, 600));

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(memsim.MemSimApp.class).getContext().getResourceMap(MemSimView.class);
        exportBtn.setText(resourceMap.getString("exportBtn.text")); // NOI18N
        exportBtn.setName("exportBtn"); // NOI18N

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        memViewer.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        memViewer.setName("memViewer"); // NOI18N
        jScrollPane1.setViewportView(memViewer);

        choicePage.setName("choicePage"); // NOI18N

        importBtn.setText(resourceMap.getString("importBtn.text")); // NOI18N
        importBtn.setName("importBtn"); // NOI18N

        choice1.setName("choiceRepresent"); // NOI18N

        storeBtn.setText(resourceMap.getString("storeBtn.text")); // NOI18N
        storeBtn.setName("storeBtn"); // NOI18N

        loadBtn.setText(resourceMap.getString("loadBtn.text")); // NOI18N
        loadBtn.setName("loadBtn"); // NOI18N

        addrLbl.setText(resourceMap.getString("addrLbl.text")); // NOI18N
        addrLbl.setName("addrLbl"); // NOI18N

        addrFld.setText(resourceMap.getString("addrFld.text")); // NOI18N
        addrFld.setName("addrFld"); // NOI18N

        cycleLbl.setText(resourceMap.getString("cycleLbl.text")); // NOI18N
        cycleLbl.setName("cycleLbl"); // NOI18N

        gotoBtn.setText(resourceMap.getString("gotoBtn.text")); // NOI18N
        gotoBtn.setName("gotoBtn"); // NOI18N

        jScrollPane2.setName("jScrollPane2"); // NOI18N

        regViewer.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null},
                {null},
                {null},
                {null}
            },
            new String [] {
                "Registers:"
            }
        ));
        regViewer.setName("regViewer"); // NOI18N
        jScrollPane2.setViewportView(regViewer);
        regViewer.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("regViewer.columnModel.title0")); // NOI18N

        stepBtn.setText(resourceMap.getString("stepBtn.text")); // NOI18N
        stepBtn.setName("stepBtn"); // NOI18N

        javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(choicePage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap(893, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 450, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, mainPanelLayout.createSequentialGroup()
                                .addComponent(exportBtn)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(importBtn)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                    .addComponent(loadBtn, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addComponent(storeBtn, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                .addGap(18, 18, 18)
                                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addGroup(mainPanelLayout.createSequentialGroup()
                                        .addComponent(addrLbl)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(addrFld)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(choice1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addGroup(mainPanelLayout.createSequentialGroup()
                                        .addComponent(gotoBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 74, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addGap(18, 18, 18)
                                        .addComponent(stepBtn)))))
                        .addGap(18, 18, 18)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 274, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(179, 179, 179))
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(cycleLbl, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap())))
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(exportBtn)
                            .addComponent(importBtn)
                            .addComponent(storeBtn)
                            .addComponent(addrLbl)
                            .addComponent(addrFld, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(loadBtn)
                                .addComponent(gotoBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(stepBtn))
                            .addComponent(choicePage, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(choice1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(10, 10, 10)
                .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 283, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(mainPanelLayout.createSequentialGroup()
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 408, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(18, 18, 18)
                        .addComponent(cycleLbl)))
                .addContainerGap(16, Short.MAX_VALUE))
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(memsim.MemSimApp.class).getContext().getActionMap(MemSimView.class, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        statusMessageLabel.setName("statusMessageLabel"); // NOI18N

        statusAnimationLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        statusAnimationLabel.setName("statusAnimationLabel"); // NOI18N

        progressBar.setName("progressBar"); // NOI18N

        javax.swing.GroupLayout statusPanelLayout = new javax.swing.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(statusPanelSeparator, javax.swing.GroupLayout.DEFAULT_SIZE, 931, Short.MAX_VALUE)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(statusMessageLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 761, Short.MAX_VALUE)
                .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(statusAnimationLabel)
                .addContainerGap())
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(statusPanelLayout.createSequentialGroup()
                .addComponent(statusPanelSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(statusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(statusMessageLabel)
                    .addComponent(statusAnimationLabel)
                    .addComponent(progressBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addGap(3, 3, 3))
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField addrFld;
    private javax.swing.JLabel addrLbl;
    private java.awt.Choice choice1;
    private java.awt.Choice choicePage;
    private javax.swing.JLabel cycleLbl;
    private javax.swing.JButton exportBtn;
    private javax.swing.JButton gotoBtn;
    private javax.swing.JButton importBtn;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JButton loadBtn;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JTable memViewer;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JProgressBar progressBar;
    private javax.swing.JTable regViewer;
    private javax.swing.JLabel statusAnimationLabel;
    private javax.swing.JLabel statusMessageLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JButton stepBtn;
    private javax.swing.JButton storeBtn;
    // End of variables declaration//GEN-END:variables

    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private MemoryTableModel memTableModel;
    private MemoryManager memView;
    private int currentRep = 0; //keeps track of the current display mode
    private String[] columnNames = new String[]{"Address:","Value:"};
    private Vector columnNamesV = new Vector(2);
    private RegisterHandler regHandler = new RegisterHandler();
    private String[] regNames = new String[]{"R0:", "R1:", "R2:", "R3:", "R4:", "R5:", "R6:", "R7:", "R8:", "R9:", "R10:", "R11:", "R12:", "R13:", "R14:", "R15:"};
    private String[] regColNames = new String[]{"Register:", "Value:"};
    private Vector regColNamesV = new Vector(2);
    private Object[][] regData;
    private Alu alu;
    private MemoryTableModel regModel;

    private final int HEX_LEN = 8;
    private boolean manualUpdate = true; //if uses refresh function, it is not a manual change

    private JDialog aboutBox;
}
